home *** CD-ROM | disk | FTP | other *** search
- {*********************************************************}
- {* HeapSort *}
- {* Copyright (c) Julian M Bucknall 1998 *}
- {* All rights reserved. *}
- {*********************************************************}
- {* Heapsort algorithm *}
- {*********************************************************}
-
- {Note: this unit is released as freeware. In other words, you are free
- to use this unit in your own applications, however I retain all
- copyright to the code. JMB}
-
- unit HeapSort;
-
- interface
-
- uses
- SysUtils, Classes;
-
- type
- TaaLessFunction = function (const X, Y : pointer) : boolean;
- {function prototype to compare two items and return true if item X
- is STRICTLY LESS than item Y}
-
- procedure AAHeapSort(var aItemArray : TList;
- aLeft, aRight : integer;
- aLessThan : TaaLessFunction);
- {-Heap sort an array (passed as a TList) in the range aLeft to
- aRight}
-
- implementation
-
- procedure AAHeapSort(var aItemArray : TList;
- aLeft, aRight : integer;
- aLessThan : TaaLessFunction);
- var
- Inx : integer;
- FromInx : integer;
- ChildInx : integer;
- ListCount: integer;
- Item : pointer;
- begin
- {if there's nothing to do, do it}
- ListCount := aRight - aLeft + 1;
- if (ListCount <= 1) then
- Exit;
-
- {first, turn the array into a heap; this is complicated by the fact
- that all our indexes are offset by aLeft}
- for Inx := ((ListCount - 2) div 2) downto 0 do begin
- Item := aItemArray[Inx+aLeft];
- FromInx := Inx;
- ChildInx := succ(FromInx * 2);
- {while there is at least a left child...}
- while (ChildInx <= aRight-aLeft) do begin
- {if there is a right child, calculate the index of the larger
- child}
- if (succ(ChildInx) <= aRight-aLeft) and
- aLessThan(aItemArray[ChildInx+aLeft], aItemArray[succ(ChildInx)+aLeft]) then
- inc(ChildInx);
- {if our item is greater or equal to the larger child, we're done}
- if not aLessThan(Item, aItemArray[ChildInx+aLeft]) then
- Break;
- {otherwise move the larger child up the tree, and move our item
- down the tree and repeat}
- aItemArray[FromInx+aLeft] := aItemArray[ChildInx+aLeft];
- FromInx := ChildInx;
- ChildInx := succ(FromInx * 2);
- end;
- {store our item in the correct place}
- aItemArray[FromInx+aLeft] := Item;
- end;
-
- {if there are only two items, the above will have sorted them}
- if (ListCount = 2) then
- Exit;
-
- {now progressively pop off the largest element and reduce the heap
- size by one, storing the largest element in the vacated space;
- again this is complicated by the fact that all our indexes are
- offset by aLeft}
- while (ListCount > 1) do begin
- {save the last item (we'll pretend it's at the root), replace it
- with the root item (ie the largest)}
- Item := aItemArray[aRight];
- aItemArray[aRight] := aItemArray[aLeft];
- {reduce the size of the heap}
- dec(ListCount);
- dec(aRight);
- {trickle down from the root}
- FromInx := 0;
- ChildInx := succ(FromInx * 2);
- {while there is at least a left child...}
- while (ChildInx <= aRight-aLeft) do begin
- {if there is a right child, calculate the index of the larger
- child}
- if (succ(ChildInx) <= aRight-aLeft) and
- aLessThan(aItemArray[ChildInx+aLeft], aItemArray[succ(ChildInx)+aLeft]) then
- inc(ChildInx);
- {if our item is greater or equal to the larger child, we're done}
- if not aLessThan(Item, aItemArray[ChildInx+aLeft]) then
- Break;
- {otherwise move the larger child up the tree, and move our item
- down the tree and repeat}
- aItemArray[FromInx+aLeft] := aItemArray[ChildInx+aLeft];
- FromInx := ChildInx;
- ChildInx := succ(FromInx * 2);
- end;
- {store our item in the correct place}
- aItemArray[FromInx+aLeft] := Item;
- end;
- end;
-
- end.
-